<?php
/**
 * Created by PhpStorm.
 * User: peiyu
 * Date: 2019/7/2
 * Time: 11:12
 */


class computeValue
{
    protected $dimension;
    protected $callback;

    public function __construct(array $dimension = [], $callback = null)
    {
        $this->dimension = $dimension;
        $this->callback = $callback;
    }

    public function check($config, array $dimensionValues = [])
    {
        //if (!$config) throw new \Exception("config is null");
        $_dimensionValues = [];
        foreach ($this->dimension as $dim) {
            $_dimensionValues[$dim] = array_get($dimensionValues, $dim, '');

        }

        $dimension = $this->dimension;
        $dimension[] = "key";
        $dimension[] = "value";
        if ($config)
            foreach ($config as $item) {
                if (count(array_intersect(array_keys($item), $dimension)) !== count($dimension)) {
                    throw new \Exception("dimension error");
                }
            }
        return $_dimensionValues;
    }

    public function compute($key, array $config, array $dimensionValues = [])
    {

        Log::debug(json_encode([$key, $config, $dimensionValues], JSON_UNESCAPED_UNICODE));
        if (!$key) throw new \Exception("key error");
        if (!$config) return null;
        $config = array_filter($config, function ($item) use ($key) {
            return ($item["key"] === $key);
        });
        if (!$config) return null;

        $catch_key = config("my.catchKEY.configValue") . md5(json_encode([$key, $config, $dimensionValues, $this->dimension]));


        $_v = cache($catch_key);
        if ($_v) {
            if ($this->callback) {
                $fun = $this->callback;
                $fun($_v);
            }
            return $_v;
        }

        $dimensionValues = self::check($config, $dimensionValues);
        $_conf = computeWeight($config, $this->dimension);
        $_value = null;


        foreach ($_conf as &$item) {
            $is_null = true;
            foreach ($this->dimension as &$dim) {
                if ($item[$dim]) {
                    $is_null = false;
                    break;
                }
            }
            if ($is_null) {
                Log::debug(json_encode($item, JSON_UNESCAPED_UNICODE));
                $_value = ["id" => $item["id"], "value" => $item["value"], "value_type" => $item["value_type"]];
                break;
            }
        }
        Log::debug(json_encode($_value, JSON_UNESCAPED_UNICODE));

        if ($dimensionValues) {
            $_config = $config;
            foreach ($this->dimension as &$dim) {
                if (!$_config) continue;
                $_dv = "";
                if (isset($dimensionValues[$dim])) $_dv = $dimensionValues[$dim];
                $_config = array_filter($_config, function ($item) use ($_dv, $dim) { //return $item["$dim"]==
                    if (!$_dv) return (!$item[$dim]);
                    return (!$item[$dim] || $item[$dim] == $_dv);
                });
                Log::debug(json_encode([$_config], JSON_UNESCAPED_UNICODE));
            }
            if ($_config) {
                $_config = array_values($_config);
                $i = count($_config) - 1;

                $_value = ["id" => $_config[$i]["id"], "value" => $_config[$i]["value"], "value_type" => $_config[$i]["value_type"]];
            }
        }
        Log::debug(json_encode($_value, JSON_UNESCAPED_UNICODE));

        if ($_value) {

            cache($catch_key, $_value, 3600);
            if ($this->callback) {
                $fun = $this->callback;
                $fun($_value);
            }
        }
        return $_value;
    }

    public function get($key, array $dimensionValues, $callback_getConfig)
    {
        if (!$key) throw new \Exception("key is null");
        if (!$callback_getConfig) throw new \Exception("callback_getConfig is null");
        $config = $callback_getConfig($key);
        $val_arr = self::compute($key, $config, $dimensionValues);
        if (!$val_arr) return $val_arr;
        $val = $val_arr["value"];
        if (!$val) return $val_arr;
        $vars = getVarFromContent($val);

        $varData = [];

        if ($vars) {
            foreach ($vars as $var) {
                $_vt_ = self::get($var, $dimensionValues, $callback_getConfig);
                if (!$_vt_) continue;
                $_v_ = $_vt_["value"];
                $varData[$var] = $_v_;
            }
            $_v_ret = contentFormat($val, $varData);


            $val_arr["value"] = $_v_ret;
        }
        if( array_get($val_arr,"value_type")=="code" ){
            $val_arr["value"]= eval($val_arr["value"]) ;

        }
        return $val_arr;
    }

}